package com.zjjc.QZEnergy.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.CipherMode;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.security.*;

public class CryptoUtils {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    // SM4 constants
    private static final String SM4_MODE = "CBC";
    private static final String SM4_PADDING= "PKCS7Padding";
    private static final int SM4_IV_SIZE = 16;  // 128 bits

    /**
     * Generate SM4 key
     */
    public static String generateSM4Key() {
        SM4 sm4 = new SM4(SM4_MODE, SM4_PADDING);
        return HexUtil.encodeHexStr(sm4.getSecretKey().getEncoded());
    }

    /**
     * Generate SM4 IV
     */
    public static String generateSM4IV() {
        byte[] iv = new byte[SM4_IV_SIZE];
        new SecureRandom().nextBytes(iv);
        return HexUtil.encodeHexStr(iv);
    }

    /**
     * SM4 encryption
     */
    public static String sm4Encrypt(String key, String data, String iv) {
        SM4 sm4 = new SM4(SM4_MODE, SM4_PADDING, HexUtil.decodeHex(key), HexUtil.decodeHex(iv));
        sm4.setMode(CipherMode.encrypt);
        return sm4.encryptHex(data);
    }

    /**
     * SM4 decryption
     */
    public static String sm4Decrypt(String key, String data, String iv) {
        SM4 sm4 = new SM4(SM4_MODE, SM4_PADDING, HexUtil.decodeHex(key), HexUtil.decodeHex(iv));
        sm4.setMode(CipherMode.decrypt);
        return sm4.decryptStr(data);
    }

    /**
     * Generate SM2 key pair
     */
    public static String[] generateSM2KeyPair() {
        SM2 sm2 = new SM2();
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        ECPublicKey publicKey = (ECPublicKey) sm2.getPublicKey();
        ECPrivateKey privateKey = (ECPrivateKey) sm2.getPrivateKey();
        // 获取公钥
        byte[] publicKeyBytes = publicKey.getQ().getEncoded(false);
        String publicKeyHex = HexUtil.encodeHexStr(publicKeyBytes);
        // 获取64位私钥
        String privateKeyHex = privateKey.getD().toString(16);
        // BigInteger转成16进制时，不一定长度为64，如果私钥长度小于64，则在前方补0
        StringBuilder privateKey64 = new StringBuilder(privateKeyHex);
        while (privateKey64.length() < 64) {
            privateKey64.insert(0, "0");
        }
        return new String[]{publicKeyHex, privateKey64.toString()};
    }

    /**
     * SM2 encryption
     */
    public static String sm2Encrypt(String publicKey, String data) {
        SM2 sm2 = new SM2(null, publicKey);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        return HexUtil.encodeHexStr(sm2.encrypt(data.getBytes()));
    }

    /**
     * SM2 decryption
     */
    public static String sm2Decrypt(String privateKey, String encryptedData) {
        if (!encryptedData.startsWith("04")) {
            encryptedData = "04" + encryptedData;
        }
        SM2 sm2 = new SM2(privateKey, null);
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        return new String(sm2.decrypt(HexUtil.decodeHex(encryptedData)));
    }

    /**
     * SM2 signature
     */
    public static String sm2Sign(String privateKey, String data) {
        SM2 sm2 = new SM2(privateKey, null);
        return HexUtil.encodeHexStr(sm2.sign(data.getBytes()));
    }

    /**
     * SM2 signature verification
     */
    public static boolean sm2Verify(String publicKey, String data, String sign) {
        SM2 sm2 = new SM2(null, publicKey);
        return sm2.verify(data.getBytes(), HexUtil.decodeHex(sign));
    }
}